#include "stdafx.h"
#include "msg/notificationcenter.hpp"
#include "msg/abstractobserver.hpp"
#include "event/scopedlock.hpp"
#include "stdlib/bugcheck.hpp"
using namespace JHCPP::stdlib;
#include "designpattern/singletonholder.hpp"
using namespace JHCPP::designpattern;

namespace JHCPP
{
	namespace msg
	{
		CNotificationCenter::CNotificationCenter()
		{
		}

		CNotificationCenter::~CNotificationCenter()
		{
		}

		void CNotificationCenter::addObserver(const CAbstractObserver& observer)
		{
			CMutex::ScopedLock lock(m_mutex);
			m_observers.push_back(observer.clone());
		}

		void CNotificationCenter::removeObserver(const CAbstractObserver& observer)
		{
			CMutex::ScopedLock lock(m_mutex);
			for (ObserverList::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
			{
				if (observer.equals(**it))
				{
					(*it)->disable();
					m_observers.erase(it);
					return;
				}
			}
		}

		void CNotificationCenter::postNotification(CNotification::Ptr pNotification)
		{
			jh_check_ptr (pNotification);

			TScopedLockWithUnlock<CMutex> lock(m_mutex);
			ObserverList observersToNotify(m_observers);
			lock.unlock();
			for (ObserverList::iterator it = observersToNotify.begin(); it != observersToNotify.end(); ++it)
			{
				(*it)->notify(pNotification);
			}
		}

		bool CNotificationCenter::hasObserver(const CAbstractObserver& observer) const
		{
			CMutex::ScopedLock lock(m_mutex);
			for (ObserverList::const_iterator it = m_observers.begin(); it != m_observers.end(); ++it)
				if (observer.equals(**it)) return true;

			return false;
		}

		bool CNotificationCenter::hasObservers() const
		{
			CMutex::ScopedLock lock(m_mutex);
			return !m_observers.empty();
		}

		std::size_t CNotificationCenter::countObservers() const
		{
			CMutex::ScopedLock lock(m_mutex);
			return m_observers.size();
		}

		static TSingletonHolder<CNotificationCenter> sh;

		CNotificationCenter& CNotificationCenter::defaultCenter()
		{
			return *sh.get();
		}
	}//end of namespace JHCPP
}//end of namespace msg
